/***********************************************************************************
 * 文 件 名   : ControlUart.c
 * 负 责 人   : jiangfeng.zhang
 * 创建日期   : 2021年6月30日
 * 文件描述   : Uart控制器驱动源文件
 * 版权说明   : Copyright (c) 2008-2021   Personal. All rights reserved.
 * 其    他   :
 * 修改日志   :
***********************************************************************************/

#include "stdio.h"
#include "string.h"
#include "stm32f4xx.h" 
#include "ControlUart.h"
#include "RingBuffer.h"
#include "FrameDataParser.h"



unsigned char  g_aucUartRepBuff[RING_BUFFER_SIZE] ;
ring_buffer    g_stRingBuff ;

/***************************************************
* 重定向代码
***************************************************/
#pragma import(__use_no_semihosting)
struct __FILE
{
    int handle;

};
/***********************************************************************
 * 函数名称: _ttywrch
 * 功能描述:
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
#if 0
_ttywrch(int ch)
{
    ch = ch;
}
#endif
FILE __stdout;
/***********************************************************************
 * 函数名称: _sys_exit
 * 功能描述:
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void _sys_exit(int x)
{
    x = x;
}

/***********************************************************************
 * 函数名称: fputc
 * 功能描述: UART1串口重定向作为调试串口,printf函数将会调用到它
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
int fputc(int ch, FILE *f)
{
    while ((USART1->SR & 0X40) == 0); //循环发送,直到发送完毕
    USART1->DR = (unsigned char) ch;
    return ch;
}



/***********************************************************************
 * 函数名称: CreatRingBuffer
 * 功能描述: 
 * 输入参数: 
 * 输出参数: 
 * 返 回 值: 
 *  其   它: 
 ***********************************************************************/
int  CreatRingBuffer()
{
	int iRet = 0;
	//初始化RingBuffer操作句柄，绑定缓冲区数组；
	iRet = Ring_Buffer_Init(&g_stRingBuff, g_aucUartRepBuff, RING_BUFFER_SIZE);
	if (iRet <= 0)
	{
		return -1;
	}
	return 0;
}
/***********************************************************************
 * 函数名称: Uart0Init
 * 功能描述: UART0初始化
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void Uart0Init(unsigned int bound)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); //使能USART1时钟
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_USART1); //GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA, GPIO_PinSource10, GPIO_AF_USART1); //GPIOA10复用为USART1
	//USART1端口配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;		//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;	 //上拉
	GPIO_Init(GPIOA, &GPIO_InitStructure);		 //初始化PA9，PA10
	//USART1 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;	//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
	USART_Init(USART1, &USART_InitStructure); //初始化串口1
	USART_Cmd(USART1, ENABLE);	//使能串口1
	
	USART_ClearFlag(USART1, USART_FLAG_TC);
	
	//USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);		 //开启相关中断
	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;	   //串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 3; //抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;		 //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; 		 //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、

}


/***********************************************************************
 * 函数名称: Uart3Init
 * 功能描述: UART0初始化
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void Uart3Init(unsigned int bound)
{   //GPIO端口设置
  	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB,ENABLE); //使能GPIOB时钟 
  	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //使能USART3时钟 
	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource10,GPIO_AF_USART3);  //GPIOB10复用为USART3
	GPIO_PinAFConfig(GPIOB,GPIO_PinSource11,GPIO_AF_USART3); //GPIOB11复用为USART3
	//USART1端口配置
  	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11; //GPIOB10与GPIOB11
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;      //复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;   //上拉
	GPIO_Init(GPIOB,&GPIO_InitStructure);          //初始化PB10，PB11
   //USART3 初始化设置
	USART_InitStructure.USART_BaudRate = bound;//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;  //一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;	//收发模式
  	USART_Init(USART3, &USART_InitStructure); //初始化串口1	
  	USART_Cmd(USART3, ENABLE);  //使能串口1 
	USART_ClearFlag(USART3, USART_FLAG_TC);
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);         //开启相关中断
	//Usart1 NVIC 配置
  	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;      //串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;		   //子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;			   //IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	  //根据指定的参数初始化VIC寄存器、
}

/***********************************************************************
 * 函数名称: ControlUartInit
 * 功能描述:
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void ControlUartInit(unsigned char ucChannel, unsigned int bound)
{
    switch (ucChannel)
    {
        case UART0_CHANNEL:
			Uart0Init(bound);
            break;
        case UART1_CHANNEL:
            break;
        case UART2_CHANNEL:
            break;
        case UART3_CHANNEL:
			Uart3Init(bound);
            break;
    }
}
/***********************************************************************
 * 函数名称: ControlUartSendData
 * 功能描述:
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void ControlUartSendData(unsigned char ucChannel, unsigned char ucData)
{
    switch (ucChannel)
    {
        case UART0_CHANNEL:
			USART_ClearFlag(USART1,USART_FLAG_TC );
            USART_SendData(USART1, ucData);
            while (USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);
			
            break;
        case UART1_CHANNEL:
            break;
        case UART2_CHANNEL:
            break;
        case UART3_CHANNEL:
			USART_ClearFlag(USART3,USART_FLAG_TC );
			USART_SendData(USART3, ucData);
            while (USART_GetFlagStatus(USART3, USART_FLAG_TC) == RESET);
            break;
    }
}

/***********************************************************************
 * 函数名称: ControlUartSwIRQ
 * 功能描述: 中断使能
 * 输入参数: 
 * 输出参数: 
 * 返 回 值: 
 *  其   它: 
 ***********************************************************************/
void ControlUartIrqEnable(unsigned char ucChannel, unsigned char ucData)
{
    switch (ucChannel)
    {
        case UART0_CHANNEL:
			if(ucData == ENABLE)
			{
				USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);		 //开启相关中断
			}
			else
			{
				USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);		 //开启相关中断
			}
            break;
        case UART1_CHANNEL:
            break;
        case UART2_CHANNEL:
            break;
        case UART3_CHANNEL:
			if(ucData == ENABLE)
			{
				USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);		 //开启相关中断
			}
			else
			{
				USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);		 //开启相关中断
			}
            break;
    }
}
/***********************************************************************
 * 函数名称: Uart1_IRQHandler
 * 功能描述: 调试串口中断服务函数
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void  USART1_IRQHandler (void)
{
	unsigned char RepData = 0;
    if (USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
			//RepData = USART_ReceiveData(USART1);	
			//shellHandler(&shell, RepData);
    }
	  USART_ClearITPendingBit(USART1, USART_IT_RXNE);
}

/***********************************************************************
 * 函数名称: USART3_IRQRecvFixDataLen
 * 功能描述: 接收定长数据,数据包不包含固定协议,如包头包尾等
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 			 数据长度参考:RECV_FIX_DATA_LEN
 ***********************************************************************/

//统计丢包数目
unsigned int   g_uiLostPackNum = 0;   


/***********************************************************************
 * 函数名称: Uart3_IRQHandler
 * 功能描述: Uart3中断服务函数,本中断服务函数用于接收Modbus通路数据,并写入环形缓冲区
 * 输入参数:
 * 输出参数:
 * 返 回 值:
 *  其   它:
 ***********************************************************************/
void  USART3_IRQHandler (void)
{
    unsigned char RepData = 0;
	int iRet = 0;
    if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
    {
	    RepData = USART_ReceiveData(USART3);	
//		iRet = FrameDataUnpack(&g_stFrame,RepData);
		iRet = FrameDataUnpackDoubleWithoutEsc(&g_stFrame,RepData);
		//此处认为解析到一组完整的数据帧
		if(iRet == FRAME_PARSER_SUCCESS)
		{
			iRet = Ring_Buffer_Write_String(&g_stRingBuff, g_stFrame.buffer,g_stFrame.len);
			if(iRet == RING_BUFFER_ERROR)
			{
				g_uiLostPackNum++;
			}
			//数据处理完成后,所有的转态进行复位
			ResetFrame(&g_stFrame);
		}
    }
	USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}






